package com.sun.springbootfiledownload.service;

import com.sun.springbootfiledownload.result.AliyunOssResult;
import com.sun.springbootfiledownload.utils.AliyunOssPlusUtil;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.concurrent.*;

/**
 * @version 1.0
 * @Package: com.sun.springbootfiledownload.service
 * @ClassName: FileQueueService
 * @Author: sgq
 * @Date: 2025/4/10 14:36
 * @Description: TODD
 */
@Slf4j
@Service
public class FileQueueService {

    @Autowired
    private AliyunOssPlusUtil aliyunOSSUtil;

    // 创建有界任务队列
    private final BlockingQueue<FileTask<?>> taskQueue = new LinkedBlockingQueue<>(100);

    // 创建单线程执行器处理队列
    private final ExecutorService executorService = Executors.newSingleThreadExecutor();

    /**
     * 初始化队列处理器
     */
    @PostConstruct
    public void init() {
        executorService.execute(this::processQueue);
    }

    /**
     * 添加上传任务到队列
     *
     * @param fileTask 文件任务
     * @return 是否添加成功
     */
    public boolean addUploadTask(FileTask fileTask) {
        return taskQueue.offer(fileTask);
    }

    /**
     * 处理队列中的任务
     */
    private void processQueue() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                // 从队列中获取任务
                FileTask<?> task = taskQueue.take();
                log.info("开始处理任务: {}", task.getFileName());

                // 执行任务
                if (task.getType() == FileTask.Type.UPLOAD) {
                    AliyunOssResult upload = aliyunOSSUtil.upload(task.getFile(), task.getFolder());
                    String fileUrl = upload.getUrl();
                    ((FileTask<String>) task).getFuture().complete(fileUrl);
                } else if (task.getType() == FileTask.Type.DOWNLOAD) {
                    InputStream download = aliyunOSSUtil.download(task.getFilePath());
                    byte[] fileContent = download.readAllBytes();
                    ((FileTask<byte[]>) task).getFuture().complete(fileContent);
                }
                log.info("任务处理完成: {}", task.getFileName());
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                log.warn("任务队列处理被中断");
            } catch (Exception e) {
                log.error("处理任务失败", e);
            }
        }
    }

    /**
     * 关闭队列处理器
     */
    @PreDestroy
    public void shutdown() {
        executorService.shutdownNow();
    }

    /**
     * 文件任务类
     */
    @Getter
    @AllArgsConstructor
    public static class FileTask<T> {
        public enum Type {UPLOAD, DOWNLOAD}

        private final Type type;
        private final MultipartFile file;      // 上传文件
        private final String filePath;        // 下载文件路径
        private final String folder;          // 上传文件夹
        private final String fileName;        // 文件名
        private final CompletableFuture<T> future; // 任务结果Future

        // 上传任务构造器
        public FileTask(MultipartFile file, String folder, CompletableFuture<T> future) {
            this.type = Type.UPLOAD;
            this.file = file;
            this.filePath = null;
            this.folder = folder;
            this.fileName = file.getOriginalFilename();
            this.future = future;
        }

        // 下载任务构造器
        public FileTask(String filePath, CompletableFuture<T> future) {
            this.type = Type.DOWNLOAD;
            this.file = null;
            this.filePath = filePath;
            this.folder = null;
            this.fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
            this.future = future;
        }
    }
}